package models

import (
	"encoding/json"
	"golang-blog/infrastructure/databases"
	"time"

	"gorm.io/gorm"
)

// 文章结构

type Article struct {
	// gorm.Model
	ID int64 `json:"id" gorm:"primaryKey"` // 主键ID
	// -------------------------------------------------------
	Title string `gorm:"type:varchar(255);comment:'标题';uniqueIndex:unique_title" json:"title"` // 标题；唯一
	// Category Category `json:"category"`                  //  类别详情
	// Cid      int      `json:"cid"`                       // 类别id
	CategoryName string `json:"category_name"`
	Status       int    `gorm:"not null;comment:'1-草稿;2-已发布'" json:"status"`
	Kind         int    `gorm:"type:int;comment:'1-文章，2-页面'" json:"kind"` //类型1-文章，2-页面
	Summary      string `gorm:"comment:'摘要'" json:"summary"`              //摘要
	Content      string `gorm:"type:longtext" json:"content"`             // 具体内容
	Img          string `gorm:"type:varchar(100)" json:"img"`             // 文章封面图片
	URLPath      string `gorm:"comment:'url访问路径'" json:"url_path"`
	// Tags         []Tag  `json:"tags"`                                          // 标签：多对多关系，新建一个表
	ReadCount    int    `gorm:"type:int;not null;default:0" json:"read_count"`    // 阅读次数
	AllowCommnet bool   `gorm:"comment:'是否允许评论'" json:"allow"`                    // 是否允许评论
	CommentCount int    `gorm:"type:int;not null;default:0" json:"comment_count"` // 评论数量
	CreatedAt    string `json:"create_at"`
	UpdatedAt    string `json:"updated_at"`
	DeletedAt    string `json:"deleted_at"`
}

func (ci *Article) String() string {
	a, _ := json.MarshalIndent(ci, "", "  ")
	return string(a)
}
func (a *Article) BeforeCreate(tx *gorm.DB) (err error) {
	a.CreatedAt = time.Now().Format("2006-01-02 15:04:05")
	a.UpdatedAt = a.CreatedAt
	return
}

func (a *Article) BeforeUpdate(tx *gorm.DB) (err error) {
	a.UpdatedAt = time.Now().Format("2006-01-02 15:04:05")
	return
}
func (a *Article) BeforeDelete(tx *gorm.DB) (err error) {
	a.DeletedAt = time.Now().Format("2006-01-02 15:04:05")
	return
}

// 文章的增删改查操作

type Articles struct {
	wheres Article
	Arts   []Article
	txn    *gorm.DB
}

func NewArticle(tx *gorm.DB) *Articles {
	if tx == nil {
		tx = databases.GetDB()
	}
	return &Articles{
		txn:  tx,
		Arts: make([]Article, 1, 32),
	}
}

func (a *Articles) With(art *Article) *Articles {
	a.Arts[0] = *art
	return a
}
func (as *Articles) Where(a *Article) *Articles {
	as.wheres = *a
	return as
}
func (as *Articles) FirstOrCreate() (*Article, error) {
	txn := as.txn.Debug().Where(&as.wheres).Attrs(&as.Arts)
	if err := txn.FirstOrCreate(&as.Arts[0]).Error; err != nil {
		return nil, err
	}
	return &as.Arts[0], nil
}
func (as *Articles) Create() (int64, error) {
	txn := as.txn.Debug().Model(&Article{})
	res := txn.Create(&as.Arts)
	return as.Arts[0].ID, res.Error
}
func (as *Articles) First() (*Article, error) {
	txn := as.txn.Debug().Model(&Article{}).Where(&as.wheres)
	if err := txn.First(&as.Arts[0]).Error; err != nil {
		return nil, err
	}
	return &as.Arts[0], nil
}
func (a *Articles) QueryRange(page, pageSize int) (*[]Article, int, int, error) {
	var (
		count     int64
		totalPage int
	)
	txn := a.txn.Debug().Model(&Article{}).Where(&a.wheres)
	if err := txn.Order("id").Offset((page - 1) * pageSize).Limit(pageSize).Find(&a.Arts).Error; err != nil {
		return nil, 0, 0, err
	}
	if err := txn.Count(&count).Error; err != nil {
		return nil, 0, 0, err
	}
	if int(count)%pageSize != 0 {
		totalPage = int(count)/pageSize + 1
	} else {
		totalPage = int(count) / pageSize
	}
	return &a.Arts, len((*a).Arts), totalPage, nil
}
func (a *Articles) Update() error {
	txn := a.txn.Debug().Model(&Article{}).Where(&a.wheres)
	if err := txn.Updates(&a.Arts[0]).Error; err != nil {
		return err
	}
	return nil
}
func (a *Articles) Delete() error {
	txn := a.txn.Debug().Model(&Article{}).Where(&a.wheres)
	if err := txn.Delete(&a.Arts).Error; err != nil {
		return err
	}
	return nil
}
func (a *Articles) Counts() (int64, error) {
	var count int64
	txn := a.txn.Debug().Model(&Article{}).Where(&a.wheres)
	if err := txn.Count(&count).Error; err != nil {
		return 0, err
	}
	return count, nil
}

func (a *Articles) Last() (*Article, error) {
	txn := a.txn.Debug().Model(&Article{}).Where(&a.wheres)
	if err := txn.Last(&a.Arts).Error; err != nil {
		return nil, err
	}
	return &a.Arts[0], nil
}
